#ifndef __FRAME_H__
#define __FRAME_H__

namespace frame {

#define UPDATE_EVERY_FRAME(func_name, update_every_frame_num, return_type)                                          \
  private:                                                                                                          \
    unsigned int _last_##func_name##_cal_frame_number{0};                                                           \
    return_type  _last_##func_name##_cal_result;                                                                    \
                                                                                                                    \
  public:                                                                                                           \
    return_type& func_name() {                                                                                      \
        if (_last_##func_name##_cal_frame_number <= frame_number_ - update_every_frame_num or frame_number_ == 0) { \
            _last_##func_name##_cal_frame_number = frame_number_;                                                   \
            _last_##func_name##_cal_result       = _##func_name();                                                  \
        }                                                                                                           \
        return _last_##func_name##_cal_result;                                                                      \
    }

#define UPDATE_EVERY_FRAME_TUPLE(func_name, update_every_frame_num, ...)                                            \
  private:                                                                                                          \
    unsigned int            _last_##func_name##_cal_frame_number{0};                                                \
    std::tuple<__VA_ARGS__> _last_##func_name##_cal_result;                                                         \
                                                                                                                    \
  public:                                                                                                           \
    std::tuple<__VA_ARGS__>& func_name() {                                                                          \
        if (_last_##func_name##_cal_frame_number <= frame_number_ - update_every_frame_num or frame_number_ == 0) { \
            _last_##func_name##_cal_frame_number = frame_number_;                                                   \
            _last_##func_name##_cal_result       = _##func_name();                                                  \
        }                                                                                                           \
        return _last_##func_name##_cal_result;                                                                      \
    }


class Frame {
  private:
    unsigned int frame_number_{0};

  public:
    void UpdateOnce() {
        ++frame_number_;
    }
};

} // namespace frame


#endif // __FRAME_H__